﻿using HMS.TenantServer.Authentication.Abstractions;
using Newtonsoft.Json;
using System.Net.Mime;
using System.Text;

namespace HMS.TenantServer.Authentication.Jwt;

public class JwtAuthenticationMiddleware : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder =>
        {
            next(builder);

            builder.UseEndpoints(endpoints =>
            {
                endpoints.MapPost("/connect/token", TokenEndpointAsync);
            });
        };
    }

    private async Task TokenEndpointAsync(HttpContext context)
    {
        try
        {
            var userPool = context.RequestServices.GetRequiredService<UserPoolBase>();
            var tokenHandler = context.RequestServices.GetRequiredService<JwtTokenHandler>();

            using var reader = new StreamReader(context.Request.Body);

            var content = await reader.ReadToEndAsync();

            var info = ExtractLoginInfo(content);

            if (info is null)
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;

                await context.Response.WriteAsync("认证失败：登录信息不完整", Encoding.UTF8);

                return;
            }

            var (claims, tenant) = await userPool.ValidateAsync(info.Value.isRoot, info.Value.account, info.Value.password);

            if (claims is not null)
            {
                var token = tokenHandler.CreateToken(claims, tenant!);

                context.Response.ContentType = MediaTypeNames.Application.Json;
                await context.Response.WriteAsync(JsonConvert.SerializeObject(token), Encoding.UTF8);
            }
            else
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;

                await context.Response.WriteAsync("认证失败", Encoding.UTF8);
            }
        }
        catch
        {
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;

            await context.Response.WriteAsync("认证失败", Encoding.UTF8);
        }
    }

    private static (bool isRoot, string account, string password)? ExtractLoginInfo(string content)
    {
        var slices = content.Split('&');

        var isrootPair = slices.FirstOrDefault(x => x.StartsWith("isroot"));
        var accountPair = slices.FirstOrDefault(x => x.StartsWith("username"));
        var passwordPair = slices.FirstOrDefault(x => x.StartsWith("password"));

        return isrootPair is null || accountPair is null || passwordPair is null
            ? null
            : (bool.Parse(isrootPair.Split('=')[1]), accountPair.Split('=')[1], passwordPair.Split('=')[1]);
    }
}